#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/configfs.h>
#include <linux/kernel.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>

// 定义dev结构体包含kobject对象

struct dev
{

    struct kobject kobj;
    int val1;
    int val2;
};

// 定义dev对象
static struct dev *device;

// 自定义kobject释放函数
static void myrelease(struct kobject *kobj)
{
    struct dev *device = container_of(kobj, struct dev, kobj);
    printk(KERN_EMERG "release kobject %p  %s", kobj, __func__);
    kfree(device);
    //释放kobject只会调用一次release
}

// 自定义show函数
ssize_t fileshow(struct kobject *kobj, struct attribute *attr, char *buf)
{
    ssize_t count = 0;
    struct dev *device = container_of(kobj, struct dev, kobj);
    if (!strcmp(attr->name, "file1"))
    {
        count = sprintf(buf, "%d\n", device->val1);
        return count;
    }
    else if (!strcmp(attr->name, "file2"))
    {
        count = sprintf(buf, "%d\n", device->val2);
        return count;
    }

    return count;
}

// 自定义store函数

ssize_t filestore(struct kobject *kobj, struct attribute *attr, const char *buf, size_t size)
{
    ssize_t ret = 0;
    struct dev *device = container_of(kobj, struct dev, kobj);
    printk("size:%lu", size);
    printk("%s", buf);
    if (!strcmp(attr->name, "file1"))
    {
        ret = sscanf(buf, "%d", &device->val1);
        printk("ret:%ld", ret);
        // if (ret != 1)
        // return -EINVAL; // Handle invalid input
        return ret;
    }
    else if (!strcmp(attr->name, "file2"))
    {
        ret = sscanf(buf, "%d", &device->val2);
        if (ret != 1)
            return -EINVAL; // Handle invalid input
        return ret;
    }
    return ret;
}

// 自定义attribute文件
struct attribute file1 = {
    .name = "file1",
    .mode = 0666};

struct attribute file2 = {
    .name = "file2",
    .mode = 0666};

// 存入attribute数组中
struct attribute *attributes[] = {
    &file1,
    &file2,
    NULL};

// 自定义attribute文件
struct attribute file3 = {
    .name = "file3",
    .mode = 0666};

struct attribute file4 = {
    .name = "file4",
    .mode = 0666};

// 存入attribute数组中
struct attribute *atts[] = {
    &file3,
    &file4,
    NULL};

// 创建组
const struct attribute_group attr_group = {
    .name = "my_group",
    .attrs = atts,
    .is_visible = NULL};

// 自定义sys_fs结构体 包含show,和store方法
struct sysfs_ops sysops = {
    .show = fileshow,
    .store = filestore};

// 自定义kobj_type结构体
static struct kobj_type mytype = {
    .release = myrelease,
    .default_attrs = attributes,
    .sysfs_ops = &sysops};

// 模块初始化代码

static int attribute_init(void)
{
    int ret;

    // 初始化dev结构体
    device = kzalloc(sizeof(struct dev), GFP_KERNEL);
    device->val1 = 1;
    device->val2 = 2;

    // 初始化dev中的kobject;
    ret = kobject_init_and_add(&device->kobj, &mytype, NULL, "%s", "myobject");
    if (ret != 0)
    {
        printk("kobject_init failed \n");
        return -1;
    }
    ret = sysfs_create_group(&device->kobj, &attr_group);
    if (ret != 0)
    {
        printk("sysfs_create failed \n");
    }
    return 0;
}

// 模块退出函数
static void attribute_exit(void)
{

    // 释放myobject
    kobject_put(&device->kobj);
    printk("attribute exit\n");
}

module_init(attribute_init);
module_exit(attribute_exit);

MODULE_LICENSE("GPL");